{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [],
   "source": [
    "import visa"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "rm=visa.ResourceManager()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## List of Commonly Used Commands"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [],
   "source": [
    "class LockInAmplifier:\n",
    "    def __init__(self, address):\n",
    "        self.address = str(address)\n",
    "        self.visa = rm.open_resource(\"GPIB0::%d::INSTR\" % address)\n",
    "        \n",
    "    ################################   \n",
    "    # Reference and Phase Commands #\n",
    "    ################################\n",
    "    \n",
    "    def phase(self, value=None):\n",
    "        if value != None:\n",
    "            self.visa.write(\"PHAS %.3f\" % value)\n",
    "            \n",
    "        reply = self.visa.query(\"PHAS?\")\n",
    "        return float(reply)\n",
    "    \n",
    "    def frequency(self, value=None):\n",
    "        if value != None:\n",
    "            self.visa.write(\"FREQ %.3f\" % value)\n",
    "        \n",
    "        reply = self.visa.query(\"FREQ?\")\n",
    "        return float(reply)\n",
    "    \n",
    "    def harmonic(self, value=None):\n",
    "        if value != None:\n",
    "            self.visa.write(\"HARM %d\" % value)\n",
    "        \n",
    "        reply = self.visa.query(\"HARM?\")\n",
    "        return int(reply)\n",
    "        \n",
    "    def amplitude(self, value=None):\n",
    "        if value != None:\n",
    "            self.visa.write(\"SLVL %.3f\" % value)\n",
    "            \n",
    "        reply = self.visa.query(\"SLVL?\")\n",
    "        return float(reply)\n",
    "\n",
    "    #############################\n",
    "    # Input and Filter Commands #\n",
    "    #############################\n",
    "    \n",
    "    def input_config(self, value=None):\n",
    "        value_mapping = ['A', 'A-B', 'I1', 'I2']\n",
    "        \n",
    "        if value != None:\n",
    "            if value not in value_mapping:\n",
    "                print('ERROR, given setting is not allowed.\\nList of allowed settings:\\n')\n",
    "                print(value_mapping)\n",
    "            else:\n",
    "                self.visa.write(\"ISRC %d\" % value_mapping.index(value))\n",
    "        \n",
    "        reply = self.visa.query(\"ISRC?\")\n",
    "        return value_mapping[int(reply)]\n",
    "    \n",
    "    def input_grounding(self, value=None):\n",
    "        value_mapping = ['Float', 'Ground']\n",
    "        \n",
    "        if value != None:\n",
    "            if value not in value_mapping:\n",
    "                print('ERROR, given setting is not allowed.\\nList of allowed settings:\\n')\n",
    "                print(value_mapping)\n",
    "            else:\n",
    "                self.visa.write(\"IGND %d\" % value_mapping.index(value))\n",
    "        \n",
    "        reply = self.visa.query(\"IGND?\")\n",
    "        return value_mapping[int(reply)]\n",
    "    \n",
    "    def input_coupling(self, value=None):\n",
    "        value_mapping = ['AC', 'DC']\n",
    "        \n",
    "        if value != None:\n",
    "            if value not in value_mapping:\n",
    "                print('ERROR, given setting is not allowed.\\nList of allowed settings:\\n')\n",
    "                print(value_mapping)\n",
    "            else:\n",
    "                self.visa.write(\"ICPL %d\" % value_mapping.index(value))\n",
    "        \n",
    "        reply = self.visa.query(\"ICPL?\")\n",
    "        return value_mapping[int(reply)]\n",
    "    \n",
    "    def notch_filter(self, value=None):\n",
    "        value_mapping = ['No filters', 'Line', '2xLine', 'Both']\n",
    "        \n",
    "        if value != None:\n",
    "            if value not in value_mapping:\n",
    "                print('ERROR, given setting is not allowed.\\nList of allowed settings:\\n')\n",
    "                print(value_mapping)\n",
    "            else:\n",
    "                self.visa.write(\"ILIN %d\" % value_mapping.index(value))\n",
    "        \n",
    "        reply = self.visa.query(\"ILIN?\")\n",
    "        return value_mapping[int(reply)]\n",
    "        \n",
    "    ###################################\n",
    "    # Gain and Time Constant Commands #\n",
    "    ###################################\n",
    "    \n",
    "    def sensitivity(self, value=None, mode='V'):\n",
    "        \n",
    "        if self.input_config() == 'A' or self.input_config() == 'A-B':\n",
    "            value_mapping = [\n",
    "                '2nV', '5nV', '10nV', '20nV', '50nV', '100nV', '200nV', '500nV', '1uV', \n",
    "                '2uV', '5uV', '10uV', '20uV', '50uV', '100uV', '200uV', '500uV', '1mV', \n",
    "                '2mV', '5mV', '10mV', '20mV', '50mV', '100mV', '200mV', '500mV', '1V'\n",
    "            ]\n",
    "        elif self.input_config() == 'I1' or self.input_config() == 'I2':\n",
    "            value_mapping = [\n",
    "                '2fA', '5fA', '10fA', '20fA', '50fA', '100fA', '200fA', '500fA', '1pA', \n",
    "                '2pA', '5pA', '10pA', '20pA', '50pA', '100pA', '200pA', '500pA', '1nA', \n",
    "                '2nA', '5nA', '10nA', '20nA', '50nA', '100nA', '200nA', '500nA', '1uA'\n",
    "            ]\n",
    "        \n",
    "        if value != None:\n",
    "            if value not in value_mapping:\n",
    "                print('ERROR, given setting is not allowed.\\nList of allowed settings:\\n')\n",
    "                print(value_mapping)\n",
    "            else:\n",
    "                self.visa.write(\"SENS %d\" % value_mapping.index(value))\n",
    "        \n",
    "        reply = self.visa.query(\"SENS?\")\n",
    "        return value_mapping[int(reply)]\n",
    "    \n",
    "    def reserve(self, value=None):\n",
    "        value_mapping = ['High Reserve', 'Normal', 'Low Noise']\n",
    "        \n",
    "        if value != None:\n",
    "            if value not in value_mapping:\n",
    "                print('ERROR, given setting is not allowed.\\nList of allowed settings:\\n')\n",
    "                print(value_mapping)\n",
    "            else:\n",
    "                self.visa.write(\"RMOD %d\" % value_mapping.index(value))\n",
    "        \n",
    "        reply = self.visa.query(\"RMOD?\")\n",
    "        return value_mapping[int(reply)]\n",
    "    \n",
    "    def time_constant(self, value=None):\n",
    "        value_mapping=[\n",
    "            '10us', '30us', '100us', '300us', \n",
    "            '1ms', '3ms', '10ms', '30ms', '100ms', '300ms', \n",
    "            '1s', '3s', '10s', '30s', '100s', '300s', \n",
    "            '1ks', '3ks', '10ks', '30ks'\n",
    "        ]\n",
    "        \n",
    "        if value != None:\n",
    "            if value not in value_mapping:\n",
    "                print('ERROR, given setting is not allowed.\\nList of allowed settings:\\n')\n",
    "                print(value_mapping)\n",
    "            else:\n",
    "                self.visa.write(\"OFLT %d\" % value_mapping.index(value))\n",
    "        \n",
    "        reply = self.visa.query(\"OFLT?\")\n",
    "        return value_mapping[int(reply)]\n",
    "    \n",
    "    def low_pass_filter(self, value=None):\n",
    "        value_mapping = ['6dB', '12dB', '18dB', '24dB']\n",
    "        \n",
    "        if value != None:\n",
    "            if value not in value_mapping:\n",
    "                print('ERROR, given setting is not allowed.\\nList of allowed settings:\\n')\n",
    "                print(value_mapping)\n",
    "            else:\n",
    "                self.visa.write(\"OFSL %d\" % value_mapping.index(value))\n",
    "        \n",
    "        reply = self.visa.query(\"OFSL?\")\n",
    "        return value_mapping[int(reply)]\n",
    "    \n",
    "    def sync_filter(self, value=None):\n",
    "        value_mapping = ['OFF', 'ON']\n",
    "        \n",
    "        if value != None:\n",
    "            if value not in value_mapping:\n",
    "                print('ERROR, given setting is not allowed.\\nList of allowed settings:\\n')\n",
    "                print(value_mapping)\n",
    "            else:\n",
    "                self.visa.write(\"SYNC %d\" % value_mapping.index(value))\n",
    "        \n",
    "        reply = self.visa.query(\"SYNC?\")\n",
    "        return value_mapping[int(reply)]\n",
    "    \n",
    "    ###############################\n",
    "    # Display and Output Commands #\n",
    "    ###############################\n",
    "    \n",
    "    def offset(self, value=None, component=1, auto=False):\n",
    "        if auto == True:\n",
    "            self.visa.write(\"AOFF %d\" % component)\n",
    "        \n",
    "        if value != None:\n",
    "            self.visa.write(\"OEXP %d,%f,%d\" % (component, value, 0))\n",
    "        \n",
    "        reply = self.visa.query(\"OEXP? %d\" % component)\n",
    "        reply = [float(i) for i in reply.split(\",\")]\n",
    "        return reply[0]\n",
    "    \n",
    "    def expand(self, value=None, component=1):\n",
    "        value_mapping = ['1x', '10x', '100x']\n",
    "        \n",
    "        # get current offset\n",
    "        reply = self.visa.query(\"OEXP? %d\" % component)\n",
    "        reply = [float(i) for i in reply.split(\",\")]\n",
    "        offset = reply[0]\n",
    "        \n",
    "        if value != None:\n",
    "            self.visa.write(\"OEXP %d,%f,%d\" % (component, offset, value_mapping.index(value)))\n",
    "        \n",
    "        reply = self.visa.query(\"OEXP? %d\" % component)\n",
    "        reply = [i for i in reply.split(\",\")]\n",
    "        return value_mapping[int(reply[1])]\n",
    "    \n",
    "    ##################\n",
    "    # Setup Commands #\n",
    "    ##################\n",
    "    \n",
    "    def save_settings(self, value=1):\n",
    "        self.visa.write(\"SSET %d\", value)\n",
    "        \n",
    "    def read_settings(self, value=1):\n",
    "        self.visa.write(\"RSET %d\", value)\n",
    "        \n",
    "    #############################\n",
    "    # Auto functions\n",
    "    #############################\n",
    "    \n",
    "    def auto_gain(self):\n",
    "        self.visa.write(\"AGAN\")\n",
    "    \n",
    "    def auto_phase(self):\n",
    "        self.visa.write(\"ARSV\")\n",
    "        \n",
    "    #########################\n",
    "    # Data transfer\n",
    "    #########################\n",
    "    \n",
    "    def output(self, component=1):\n",
    "        reply = self.visa.query(\"OUTP? %d\" % component)\n",
    "        return float(reply)\n",
    "    \n",
    "    def snap(self):\n",
    "        reply = self.visa.query(\"SNAP?1,2,3,4\")\n",
    "        data = [float(i) for i in reply.split(\",\")]\n",
    "        return data\n",
    "    \n",
    "    ########################\n",
    "    # Interface\n",
    "    ########################\n",
    "    \n",
    "    # Reset the unit to its default configurations\n",
    "    def reset(self):\n",
    "        self.visa.write(\"*RST\")\n",
    "        \n",
    "    def idn(self):\n",
    "        reply = self.visa.query(\"*IDN?\")\n",
    "        return reply\n",
    "    \n",
    "    ########################\n",
    "    # Status\n",
    "    ########################\n",
    "    \n",
    "    def serial_poll_status(self, value=None):\n",
    "        value_mapping=[\n",
    "            'Scan', 'Command', 'Error', 'LIA status', 'Interface output buffer', 'Standard status', 'Service request'\n",
    "        ]\n",
    "        \n",
    "        if value not in value_mapping:\n",
    "            print('ERROR, given setting is not allowed.\\nList of allowed settings:\\n')\n",
    "            print(value_mapping)\n",
    "        else:\n",
    "            reply = self.visa.query(\"*STB? %d\" % value_mapping.index(value))\n",
    "            return not bool(reply)\n",
    "    \n",
    "    def lia_status(self, value=None):\n",
    "        value_mapping=[\n",
    "            'Reserve/Input', 'Filter', 'Output', 'Unlock', 'Range', 'Time Constant',\n",
    "        ]\n",
    "        \n",
    "        if value not in value_mapping:\n",
    "            print('ERROR, given setting is not allowed.\\nList of allowed settings:\\n')\n",
    "            print(value_mapping)\n",
    "        else:\n",
    "            reply = self.visa.query(\"LIAS? %d\" % value_mapping.index(value))\n",
    "            return not bool(reply)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [],
   "source": [
    "li1=LockInAmplifier(7)\n",
    "li2=LockInAmplifier(8)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.004"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "li1.amplitude()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "7.8666e-10 0.00011921\n"
     ]
    }
   ],
   "source": [
    "print(li1.output(),li2.output())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "10nA 20mV\n"
     ]
    }
   ],
   "source": [
    "print(li1.sensitivity('10nA'), li2.sensitivity('20mV'))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "-0.0881276"
      ]
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "li2.output()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'200mV'"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "li2.sensitivity('200mV')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 549,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(11, <StatusCode.success: 0>)"
      ]
     },
     "execution_count": 549,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "li2.visa.write(\"OEXP 1,11\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'10x'"
      ]
     },
     "execution_count": 46,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "li1.expand('10x')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
